﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace Walson.Tools
{
    static public class Converter
    {
        /// <summary>
        /// 结构/类转换为字节数组
        /// </summary>
        /// <param name="structObj">要进行转换的结构或类</param>
        /// <returns>字节数组</returns>
        static public byte[] StructToBytes(object structObj)
        {
            int size = Marshal.SizeOf(structObj);
            byte[] bytes = new byte[size];
            IntPtr structPtr = Marshal.AllocHGlobal(size);
            Marshal.StructureToPtr(structObj, structPtr, false);
            Marshal.Copy(structPtr, bytes, 0, size);
            Marshal.FreeHGlobal(structPtr);
            return bytes;
        }

        /// <summary>
        /// 字节数组转换为结构体/类
        /// </summary>
        /// <typeparam name="T">目标类型</typeparam>
        /// <param name="bytes">字节数组</param>
        /// <param name="type">目标类型</param>
        /// <returns>目标结构/类</returns>
        static public T BytesToStruct<T>(byte[] bytes, Type type)
        {
            int size = Marshal.SizeOf(type);
            if (size < bytes.Length)
                return default(T);

            IntPtr structPtr = Marshal.AllocHGlobal(size);
            Marshal.Copy(bytes, 0, structPtr, Math.Min(size, bytes.Length));
            object obj = Marshal.PtrToStructure(structPtr, type);
            Marshal.FreeHGlobal(structPtr);
            return (T)obj;
        }
    }

    /// <summary>
    /// 比较
    /// </summary>
    static public class Comparison
    {
        [DllImport("msvcrt.dll")]
        private static extern IntPtr memcmp(byte[] b1, byte[] b2, IntPtr count);

        /// <summary>  
        /// 用memcmp比较字节数组  
        /// </summary>  
        /// <param name="bytes1">字节数组1</param>  
        /// <param name="bytes2">字节数组2</param>  
        /// <returns>如果两个数组相同，返回0；如果数组1小于数组2，返回小于0的值；如果数组1大于数组2，返回大于0的值。</returns>  
        public static int MemoryCompare(byte[] bytes1, byte[] bytes2)
        {
            IntPtr retval = memcmp(bytes1, bytes2, new IntPtr(bytes1.Length));
            return retval.ToInt32();
        } 
    }
    
}
